﻿using System;
using System.Linq;
using NUnit.Core;
using NUnit.Util;

namespace QuickTest.Core.TestRunner
{
    /// <summary>
    /// The NUnitTestRunner class provides the functionality for running NUnit tests.
    /// </summary>
    public class NUnitTestRunner : MarshalByRefObject, ITestRunner
    {
        #region Constructors

        public NUnitTestRunner()
        {
            RegisterTestServices();
        }

        #endregion

        #region Methods

        private static void RegisterTestServices()
        {
            // These services are required by NUnit
            ServiceManager.Services.AddService(new SettingsService());
            ServiceManager.Services.AddService(new DomainManager());
            ServiceManager.Services.AddService(new AddinRegistry());
            ServiceManager.Services.AddService(new AddinManager());
            ServiceManager.Services.InitializeServices();
            AppDomain.CurrentDomain.SetData("AddinRegistry", NUnit.Util.Services.AddinRegistry);
            if (!CoreExtensions.Host.Initialized)
            {
                CoreExtensions.Host.InitializeService();
            }
        }

        /// <summary>
        /// Runs all tests in a package.
        /// </summary>
        public void Run(ITestPackage testPackage, ITestEvents events)
        {
            if (testPackage == null)
                throw new ArgumentNullException("testPackage");

            var package = new NUnit.Core.TestPackage(String.Empty, testPackage.Assemblies.ToArray());
            TestSuite suite = new TestSuiteBuilder().Build(package);

            if (suite == null)
            {
                events.RaiseRunFinished(new TestRunFinishedEventArgs(0, 0, 0, 0));
                return;
            }

            int testCount = suite.CountTestCases(TestFilter.Empty);
            EventListener eventListener = new NUnitEventListener(events);

            eventListener.RunStarted(String.Empty, testCount);

            NUnit.Core.TestResult result = suite.Run(eventListener);

            eventListener.RunFinished(result);
        }

        #endregion
    }
}